package cut_stock_2;

import gurobi.GRB;
import gurobi.GRBEnv;
import gurobi.GRBException;
import gurobi.GRBLinExpr;
import gurobi.GRBModel;
import gurobi.GRBVar;

import Jama.Matrix;

public class MainProblem {

    private GRBEnv env;
    private GRBModel model;
    private int xNum;
    private int cNum;

    public Matrix solutions; // 决策变量的值，列向量
    public Matrix shadowPrice; // 对偶变量的值，行向量

    MainProblem(Matrix A, Matrix b) {
        xNum = A.getColumnDimension();
        cNum = A.getRowDimension();

        try {
            env = new GRBEnv(true);
            env.start();
            model = new GRBModel(env);
            model.set("OutputFlag", "0");

            // 创建决策变量
            GRBVar[] x = model.addVars(xNum, GRB.CONTINUOUS);

            // 设置目标函数
            GRBLinExpr expr = new GRBLinExpr();
            expr.addTerms(new Matrix(1, xNum, 1).getArray()[0], x);
            model.setObjective(expr, GRB.MINIMIZE);

            // 添加约束
            for (int i = 0; i < cNum; i++) {
                expr = new GRBLinExpr();
                expr.addTerms(A.getMatrix(i, i, 0, xNum - 1).getArray()[0], x);
                model.addConstr(expr, GRB.GREATER_EQUAL, b.get(i, 0), "c0");
            }
        } catch (GRBException e) {
            System.out.println("Error code: " + e.getErrorCode() + ". " +
                    e.getMessage());
        }
    }

    public void solve() {

        try {

            // 求解模型
            model.optimize();

            // 读取决策变量的值
            solutions = new Matrix(xNum, 1, 0);
            if (model.get(GRB.DoubleAttr.ObjVal) > 0) {
                for (int i = 0; i < xNum; i++) {
                    solutions.set(i, 0, model.getVars()[i].get(GRB.DoubleAttr.X));
                }
            }

            // 获取对偶变量的值
            shadowPrice = new Matrix(model.get(GRB.DoubleAttr.Pi, model.getConstrs()), cNum);

            model.dispose();
            env.dispose();

        } catch (GRBException e) {
            System.out.println("Error code: " + e.getErrorCode() + ". " + e.getMessage());
        }

    }

}
